﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Grafika_WPF.Components;
using Light = Grafika_WPF.Components.Light;

namespace Grafika_WPF.Helpers
{
    public static class Converter
    {
        public static Point CastTo2dPoint(Point3D point, Point3D center, Vector3D horizontalMove, Vector3D verticalMove)
        {

            double hor = center.X * verticalMove.Y - center.Y * verticalMove.X - point.X * verticalMove.Y +
                         point.Y * verticalMove.X;
            double ver = -center.X * horizontalMove.Y + center.Y * horizontalMove.X + point.X * horizontalMove.Y -
                         point.Y * horizontalMove.X;

            double div = horizontalMove.Y * verticalMove.X - horizontalMove.X * verticalMove.Y;

            hor /= div;
            ver /= div;
            
			int hPixelOffset = -(int)(hor + 0.5);
            int vPixelOffset = -(int)(ver + 0.5);
            return new Point(hPixelOffset,vPixelOffset);
        }
        public static Point3D ProjectPointToAPlane(
             Point3D point,
             double A,
             double B,
             double C,
             double D,
             Vector3D projectionDirection)
        {
            double t = -(A * point.X + B * point.Y + C * point.Z + D) /
                (A * projectionDirection.X + B * projectionDirection.Y + C * projectionDirection.Z);
            return point + t * projectionDirection;
        }

        public static Color CalculateLightColor(IEnumerable<Light>lights,double ambientLight,Vector3D normal,Color color)
        {
            double r = 0;
            double g = 0;
            double b = 0;
            foreach (var light in lights)
            {
                double angle = Math.Abs(Vector3D.AngleBetween(normal, light.Direction));
                if(angle<90)
                {
                    var cos = Math.Cos(2*Math.PI*angle/360);
                    r += light.Intense*color.R*cos;
                    g += light.Intense*color.G*cos;
                    b += light.Intense*color.B*cos;
                }
            }
            r += color.R*ambientLight;
            g += color.G*ambientLight;
            b += color.B*ambientLight;

            r = r > 255 ? 255 : r;
            g = g > 255 ? 255 : g;
            b = b > 255 ? 255 : b;


            return Color.FromRgb((byte)(r),(byte)g, (byte)(b));
        }

        public static Color CalculatePhongColor(
            Triangle t,
            Point3D p,
            Color aColor,
            Color bColor,
            Color cColor)
        {
            double distA = GetPointDistanceFromLine(t.A, t.B, t.C);
            double distB = GetPointDistanceFromLine(t.B, t.C, t.A);
            double distC = GetPointDistanceFromLine(t.C, t.A, t.B);

            double coeffA = GetPointDistanceFromLine(p, t.B, t.C) / distA;
            double coeffB = GetPointDistanceFromLine(p, t.C, t.A) / distB;
            double coeffC = GetPointDistanceFromLine(p, t.A, t.B) / distC;
            double nominative = coeffA + coeffB + coeffC;

            double r = aColor.R * coeffA + bColor.R * coeffB + cColor.R * coeffC;
            r /= nominative;
            double g = aColor.G * coeffA + bColor.G * coeffB + cColor.G * coeffC;
            g /= nominative;
            double b = aColor.B * coeffA + bColor.B * coeffB + cColor.B * coeffC;
            b /= nominative;

            if (r > 255)
                r = 255;
            if (g > 255)
                g = 255;
            if (b > 255)
                b = 255;

            return Color.FromRgb((byte)r, (byte)g, (byte)b);
        }

        private  static double GetPointDistanceFromLine(Point3D p, Point3D l1, Point3D l2)
        {
            return Vector3D.CrossProduct(p - l1, p - l2).Length / (l2 - l1).Length;
        }
        
    }
}
